<div class="view">

    <!-- 绘制图表 -->
    <div id="tips" class="tips"></div>
    <div id="content" class="content"></div>

    <!-- 悬浮提示 -->
    <div id="tooltip" class="tooltip"></div>
</div>
<script type="module">

    import { WebGL, Canvas, animation, rotate, getLoopColors, formatColor } from "vislite";

    var i, j;

    var data = [
        { value: 1048, name: 'Search Engine' },
        { value: 735, name: 'Direct' },
        { value: 580, name: 'Email' },
        { value: 484, name: 'Union Ads' },
        { value: 300, name: 'Video Ads' }
    ];

    var colors = getLoopColors(data.length);

    var colors3d = [];
    for (i = 0; i < colors.length; i++) {
        colors3d.push(formatColor(colors[i], "3d"));
    }

    var colors_gray = getLoopColors(data.length, 0.9);

    var colors3d_gray = [];
    for (i = 0; i < colors.length; i++) {
        colors3d_gray.push(formatColor(colors_gray[i], "3d"));
    }

    var mycontent = document.getElementById("content");
    var mytooltip = document.getElementById("tooltip");

    var painter, updateView;

    var beginDeg, deg, allValue = 0;

    var innerRadius = 1, outerRadius = 1.6;
    var deepLen = 0.1;

    // 求解值总数
    for (i = 0; i < data.length; i++) {
        allValue += data[i].value;
    }

    var doit = function () {
        painter = new WebGL(mycontent);

        var tipsPainter = new Canvas(document.getElementById('tips'));

        // 绘制标题
        tipsPainter.config({
            "textAlign": "center",
            "fontSize": 20,
            "fontWeight": 600

        }).fillText("Referer of a Website", mycontent.clientWidth * 0.5, 30)
            .config({
                "fontWeight": 200,
                "fontSize": 12
            }).fillText("Fake Data", mycontent.clientWidth * 0.5, 60);

        // legend提示
        tipsPainter.config({
            "textAlign": "left"
        });
        for (i = 0; i < data.length; i++) {
            tipsPainter.config({
                "fillStyle": "black"
            }).fillText(data[i].name, 50, i * 24 + 50)
                .config({
                    "fillStyle": colors[i]
                }).fillRect(20, i * 24 + 40, 25, 16);

        };

        beginDeg = Math.PI * -0.5;

        for (i = 0; i < data.length; i++) {
            deg = data[i].value / allValue * Math.PI * 2;

            var stripTriangles = {
                top: [],
                bottom: [],
                near: [],
                far: []
            }

            // 计算切割份数
            var splitNum = Math.ceil(deg * mycontent.clientHeight * 0.1);

            var perDeg = deg / splitNum;
            for (j = 0; j <= splitNum; j++) {

                var positionOuter = rotate(0, 0, beginDeg + perDeg * j, outerRadius, 0);
                var positionInner = rotate(0, 0, beginDeg + perDeg * j, innerRadius, 0);

                stripTriangles.top.push(
                    positionOuter[0], positionOuter[1], deepLen,
                    positionInner[0], positionInner[1], deepLen
                );

                stripTriangles.bottom.push(
                    positionOuter[0], positionOuter[1], -deepLen,
                    positionInner[0], positionInner[1], -deepLen
                );

                stripTriangles.near.push(
                    positionInner[0], positionInner[1], deepLen,
                    positionInner[0], positionInner[1], -deepLen
                );

                stripTriangles.far.push(
                    positionOuter[0], positionOuter[1], deepLen,
                    positionOuter[0], positionOuter[1], -deepLen
                );

            }

            painter.render({
                matrix: painter.matrix().rotate(-1, 1, 0, 0),
                region: "index" + i,
                mesh: [{
                    geometry: {
                        attributes: {
                            position: {
                                array: stripTriangles.top,
                                count: (splitNum + 1) * 2,
                                itemSize: 3
                            }
                        },
                        type: "TRIANGLE_STRIP"
                    },
                    material: {
                        color: {
                            r: colors3d[i][0],
                            g: colors3d[i][1],
                            b: colors3d[i][2],
                            alpha: colors3d[i][3]
                        }
                    }
                }, {
                    geometry: {
                        attributes: {
                            position: {
                                array: stripTriangles.bottom,
                                count: (splitNum + 1) * 2,
                                itemSize: 3
                            }
                        },
                        type: "TRIANGLE_STRIP"
                    },
                    material: {
                        color: {
                            r: colors3d[i][0],
                            g: colors3d[i][1],
                            b: colors3d[i][2],
                            alpha: colors3d[i][3]
                        }
                    }
                }, {
                    geometry: {
                        attributes: {
                            position: {
                                array: stripTriangles.near,
                                count: (splitNum + 1) * 2,
                                itemSize: 3
                            }
                        },
                        type: "TRIANGLE_STRIP"
                    },
                    material: {
                        color: {
                            r: colors3d_gray[i][0],
                            g: colors3d_gray[i][1],
                            b: colors3d_gray[i][2],
                            alpha: colors3d_gray[i][3]
                        }
                    }
                }, {
                    geometry: {
                        attributes: {
                            position: {
                                array: stripTriangles.far,
                                count: (splitNum + 1) * 2,
                                itemSize: 3
                            }
                        },
                        type: "TRIANGLE_STRIP"
                    },
                    material: {
                        color: {
                            r: colors3d_gray[i][0],
                            g: colors3d_gray[i][1],
                            b: colors3d_gray[i][2],
                            alpha: colors3d_gray[i][3]
                        }
                    }
                }]
            })

            beginDeg += deg;
        }
    };
    doit();

    // 监听画布大小改变
    window.addEventListener("resize", doit);

    // 当前被悬浮的区域
    var currentRegion;

    // 注册鼠标悬浮事件
    var stop = function () { };
    mycontent.addEventListener('mousemove', function (event) {
        if (painter) {
            painter.getRegion(event.offsetX, event.offsetY).then(function (regionName) {
                if (regionName) {

                    if (!currentRegion) {

                        // 显示悬浮框
                        mytooltip.style.display = "";

                    }

                    // 如果悬浮区域改变了
                    if (regionName != currentRegion) {
                        stop();

                        var _currentRegion = currentRegion;
                        currentRegion = regionName;

                        var index = regionName.replace('index', '');

                        // 修改悬浮框内容
                        mytooltip.innerHTML = "<div style='border-color:" + colors[index] + "'><label>Access From</label>" +
                            "<i style='background-color:" + colors[index] + "'></i>" +
                            "<span>" + data[index].name + "</span>" +
                            "<span>" + data[index].value + "</span></div>";

                    }

                    // 修改悬浮框位置
                    if (event.offsetX > mytooltip.clientWidth * 0.5) {
                        mytooltip.style.left = (event.offsetX - 20 - mytooltip.clientWidth) + "px";
                    } else {
                        mytooltip.style.left = (event.offsetX + 20) + "px";
                    }
                    mytooltip.style.top = (event.offsetY + 20) + "px";

                } else {

                    // 如果当前存在悬浮区域
                    if (currentRegion) {
                        stop();

                        var _currentRegion = currentRegion;
                        currentRegion = undefined;

                        // 隐藏悬浮框
                        mytooltip.style.display = "none";
                    }

                }

            });
        }
    });

</script>
<style>
    body {
        margin: 0;
    }

    .tips {
        width: 100vw;
        height: 100vh;
    }

    .content {
        width: 100vw;
        height: 100vh;
        position: absolute;
        left: 0;
        top: 0;
    }

    .view {
        position: relative;
    }

    .tooltip {
        position: absolute;
        transition-duration: 300ms;
        transition-timing-function: linear;
        transition-property: left top;
        pointer-events: none;
    }

    .tooltip>div {
        box-shadow: rgb(0 0 0 / 20%) 1px 2px 10px;
        border-style: solid;
        background-color: rgb(255, 255, 255);
        border-width: 1px;
        border-radius: 4px;
        color: rgb(102, 102, 102);
        font: 14px / 21px sans-serif;
        padding: 10px;
        text-align: left;
    }

    .tooltip>div>label {
        font-size: 14px;
        color: #666;
        font-weight: 400;
        line-height: 1;
        display: block;
    }

    .tooltip>div>i {
        display: inline-block;
        width: 10px;
        height: 10px;
        border-radius: 50%;
        vertical-align: middle;
        margin: 0 5px;
    }

    .tooltip>div>span {
        font-size: 14px;
        color: #666;
        font-weight: 400;
    }

    .tooltip>div>span:last-child {
        padding-left: 30px;
        font-weight: 900;
    }
</style>